using System;
using System.Collections.Generic;
using System.Text;
using OpenComposite.EII.Repository;
using OpenComposite.Base.Designer;
using OpenComposite.Base;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using System.IO;
using System.Collections.ObjectModel;
using System.Xml;
using OpenComposite.EII.Designer.Generic;
using OpenComposite.EII.Services;

namespace OpenComposite.EII.Designer.BRules
{
	public class BRulesDesignController : DesignController
	{
		public BRulesDesignController(RepositorySurfaceManager surfaceManager)
			: base(surfaceManager)
		{
		}

		#region Public Members

		#region Override
		public override bool Save()
		{
			Global.Data.DeleteRepositoryChildHierarchy(this.RepositoryItem);
			bool ok = base.Save();
			if ( !ok )
				return false;

			// TODO: Save Business Policy Item
			List<string> listPolicyResults = new List<string>();
			//List<BusinessRule> listRules = new List<BusinessRule>();
			BusinessPolicy policy = this.DiagramItem as BusinessPolicy;
			if ( policy == null )
				return false;
			// collect rule informations				
			foreach ( DesignerControl ctrl in this.DesignerView.DesignerControls.ControlsWithoutRoutes ) {
				BusinessRuleSymbol brulesymbol = ctrl as BusinessRuleSymbol;
				if ( brulesymbol == null )
					continue;
				//if ( repSvc != null ) {
					try {
						ItemType type = (ItemType)Global.Data.GetRepositoryHierarchyParents(DiagramItem).Rows[0]["parent_reptype_id"];
						if ( type == ItemType.GenericFolder ) {
							brulesymbol.RepositoryRule.NText = this.DiagramItem.Name;
						}
					} catch { }
				//}
				//RepositoryBusinessRule brule = brulesymbol.RepositoryItem as RepositoryBusinessRule;
				//if ( brule == null )
				//    continue;
				//bool tst = brule.Load(brule.ID);
				//listRules.Add(brule.BusinessRule);

				foreach ( THENResultSymbol thenSym in brulesymbol.ThenList ) {
					if ( !string.IsNullOrEmpty(thenSym.ResultString) ) {
						listPolicyResults.Add(thenSym.ResultString);
					}
				}
				if ( !string.IsNullOrEmpty(brulesymbol.Else.ResultString) ) {
					listPolicyResults.Add(brulesymbol.Else.ResultString);
				}
			}

			//string code = CodeGenerators.BusinessPolicyCodeGenerator.GenerateBusinessPolicyClass(
			//     base._surfaceManager, policy.Name, listRules, listPolicyResults);

			//if ( code != CodeGenerators.BusinessPolicyCodeGenerator.ERROR ) {
			//policy.PolicyCode = code;
			policy.PolicyResultStrings = listPolicyResults;
			policy.Save();
			//}

			return ok;
		}
		protected override void OnLoaded()
		{
			this.RepositoryItem.ItemDeleted += new RepositoryEventHandler(RepositoryItem_ItemDeleted);
			base.OnLoaded();
		}

		void RepositoryItem_ItemDeleted(object sender, RepositoryEventArgs e)
		{
			this.Close();
		}
		#endregion

		#endregion

		#region Protected Members

		#region Override
		protected override void LoadDiagram()
		{
			if ( this.DiagramItem == null )
				throw new NullReferenceException("DiagramItem == null.");

			if ( this.DiagramItem.Diagram != null ) {
				// load diagram
				this.DesignerView.BeginUpdate();
				this.DesignerView.LoadDiagramFromXml(this.DiagramItem.Diagram, this.DesignerControlTypes.ToArray());
				this.DesignerView.EndUpdate();
			}
			LoadItems();
		}
		protected override void RecursiveSaveItems(OpenComposite.Base.Designer.DesignerControl dcCurrent, OpenComposite.EII.Repository.IRepositoryItem itemParent)
		{
			base.RecursiveSaveItems(dcCurrent, itemParent);
		}

		protected override void OnDragDrop(System.Windows.Forms.DragEventArgs e)
		{
			_changed = true;
			RepositoryService repSvc = (RepositoryService)this.GetService(typeof(RepositoryService));
			Debug.Assert(repSvc != null);
			if ( e.Data.GetDataPresent(typeof(RepositoryBusinessRule)) ) {
				RepositoryBusinessRule tempRule = e.Data.GetData(typeof(RepositoryBusinessRule)) as RepositoryBusinessRule;
				if ( tempRule.Diagram == null ) {
					MessageBox.Show("Please open and save the Businesss Policy containing the Business Rule to drop and try again.", 
						"Missing information", MessageBoxButtons.OK, MessageBoxIcon.Information);
					return;
				}
				IRepositoryItem parent = this.DiagramItem as IRepositoryItem;
				RepositoryBusinessRule repRule = repSvc.GetNewItem<RepositoryBusinessRule>(false, ref parent);
				repRule.Name = tempRule.Name;
				repRule.Diagram = tempRule.Diagram;
				Point newLocation = this.DesignerView.PointToClient(new Point(e.X, e.Y));
				BusinessRuleSymbol brule = LoadBusinessRuleFromXmlDiagram(repRule, newLocation);

			} else if ( e.Data.GetDataPresent(typeof(ItemType)) ) {
				ItemType type = (ItemType)e.Data.GetData(typeof(ItemType));
				bool bShowInputDlg = !( type == ItemType.SCA_Export || type == ItemType.SCA_Import ||
										type == ItemType.Selector );
				DesignerControl ctrl = repSvc.CreateDesignerControl(type, bShowInputDlg, this.DiagramItem);
				if ( ctrl != null ) {
					BusinessPolicy policy = this.DiagramItem as BusinessPolicy;
					if ( policy != null && policy.NText == BusinessPolicy.cParticipantPolicy ) {
						if ( ctrl is THENResultSymbol ) {
							ctrl = new ParticipantRules.THENParticipantSymbol();
							ctrl.InitializeNew(this);
						}
					}
					if ( ctrl.UseGrid )
						ctrl.Location = this.DesignerView.PointToGrid(this.DesignerView.PointToClient(
							new Point(e.X, e.Y)));
					else
						ctrl.Location = this.DesignerView.PointToClient(new Point(e.X, e.Y));
					//addRepositoryItemToMainControlParent(ctrl);
					this.DesignerView.BeginUpdate();
					this.DesignerView.DropObject(ctrl, ctrl.Location, MouseButtons.Left);
					this.DesignerView.EndUpdate();
				}
			} else {
				base.OnDragDrop(e);
			}
		}

		private BusinessRuleSymbol addSerializedRule(XmlNode xn)
		{
			BusinessRuleSymbol symbol = null;
			Type type = null;
			try {
				if ( type == null )
					type = Type.GetType(xn.Attributes["Type"].Value);
			} catch {
				type = null;
			}
			if ( type != null ) {
				System.Reflection.ConstructorInfo ctor = type.GetConstructor(Type.EmptyTypes);
				symbol = (BusinessRuleSymbol)ctor.Invoke(new object[0]);
				if ( symbol != null ) {
					symbol.BeginUpdate();
					this.DesignerView.AddDesignerControl(symbol);
					try {
						symbol.AllowReadingRoutes = true;
						symbol.ReadXml(new XmlNodeReader(xn));
						symbol.AllowReadingRoutes = false;
						symbol.InitializeLoaded();
					} catch {
						if ( symbol != null ) {
							this.DesignerView.DesignerControls.Remove(symbol);
							symbol = null;
						}
					} finally {
						symbol.EndUpdate();
					}
				}
			}
			return symbol;
		}

		public BusinessRuleSymbol LoadBusinessRuleFromXmlDiagram(RepositoryBusinessRule repRule, Point location, Type[] types)
		{
			base._listDesignerControlTypes = new List<Type>(types);
			return LoadBusinessRuleFromXmlDiagram(repRule, location);
		}

		public BusinessRuleSymbol LoadBusinessRuleFromXmlDiagram(RepositoryBusinessRule repRule, Point location)
		{
			BusinessRuleSymbol symbol = null;
			XmlDocument xd = repRule.Diagram;

			XmlSerializer xs = new XmlSerializer(typeof(DesignerControl));
			XmlNodeList xnlControls = xd.SelectNodes("/DesignerDiagram/BusinessRule/BusinessRuleSymbol");
			// place the new rule at correct position
			if ( location != Point.Empty ) {
				XmlNode xRc = xd.SelectSingleNode("/DesignerDiagram/BusinessRule/BusinessRuleSymbol/Bounds");
				RectangleConverter rc = new RectangleConverter();
				Rectangle old = (Rectangle)rc.ConvertFromString(xRc.InnerText);
				xRc.InnerText = rc.ConvertToString(new Rectangle(location, old.Size));
			}
			// set new id
			XmlNode xId = xd.SelectSingleNode("/DesignerDiagram/BusinessRule/BusinessRuleSymbol/RepositoryBusinessRule");
			xId.Attributes["id"].Value = repRule.ID.ToString();
			// create designer control and add to DesignerControls collection
			symbol = addSerializedRule(xnlControls[0]);

			return symbol;
		}

		#endregion

		#endregion
	}
}
